#include "stdafx.h"

#include "Player.h"
#include "Dialogue.h"
#include "GameObject.h"
#include "SolidMap.h"
#include "Inventory.h"
#include "HiddenObject.h"

sf::Vector2u gScreenSize;

sf::Sprite maleLaddersSprite;
sf::Sprite maleHalfMaskSprite;

sf::Sprite gLevelBackground;
sf::Sprite gMaleVision;

sf::Vector2f currLookAt;

sf::View gView;

enum AreaType
{
	AT_MALE,
	AT_FEMALE,
	AT_NORMAL,
	AT_BOTH
};

extern int hiddenObjCount;
extern sf::Sound gWinSound;

void DrawArea(AreaType type, sf::RenderWindow& window, sf::View& view, sf::FloatRect viewport)
{
	int x = viewport.left;
	int y = viewport.top;
	int w = viewport.width;
	int h = viewport.height;

	if(x < 0) { w += x; x = 0; }
	if(y < 0) { h += y; y = 0; };
	if(w <= 0 || h <= 0) return;

	glEnable(GL_SCISSOR_TEST);
	glScissor(x, gScreenSize.y - y - h, w, h);

	if(type == AT_MALE || type == AT_BOTH)
	{
		window.draw(gMaleVision);
	}

	sf::RectangleShape rs(sf::Vector2f(50000.0f, 50000.0f));
	if(type == AT_NORMAL)
		rs.setFillColor(sf::Color(0, 0, 255, 64));
	else if(type == AT_MALE)
		rs.setFillColor(sf::Color(0, 255, 0, 64));
	else if(type == AT_FEMALE)
		rs.setFillColor(sf::Color(255, 0, 0, 64));
	else
		rs.setFillColor(sf::Color(255, 255, 255, 64));
	//rs.setOrigin(25000.0f, 25000.0f);

	//if(type != AT_NORMAL)
	//	window.draw(rs);

	for(unsigned int i=0; i<gGameObjects.size(); i++)
	{
		if(
			((type == AT_BOTH || type == AT_FEMALE) && gGameObjects[i]->type == GOT_FEMALE_VISIBLE) ||
			((type == AT_BOTH || type == AT_MALE) && gGameObjects[i]->type == GOT_MALE_VISIBLE) || gGameObjects[i]->type == GOT_NORMAL)
			gGameObjects[i]->Draw(window);
	}

	glDisable(GL_SCISSOR_TEST);
}

void DrawLevel(sf::RenderWindow& window, int& frames, sf::View& view, sf::Clock& fpsTimer, float viewHeight)
{
	frames++;
	if(fpsTimer.getElapsedTime().asSeconds() > 1.0f)
	{
		std::cout << "FPS: "<<frames<<"\n";
		frames = 0;
		fpsTimer.restart();
	}

	sf::Vector2u screenSize = window.getSize();
	if(screenSize.x == 0) screenSize.x = 0;
	view.setSize(sf::Vector2f(viewHeight *  screenSize.x / screenSize.y, viewHeight));
	view.setCenter(currLookAt);

	window.setView(view);

	sf::Vector2f center = sf::Vector2f(gMale.pos.x, gFemale.pos.y);
	sf::Vector2f A = center + sf::Vector2f(-VIEW_SIZE/2.0f, -VIEW_SIZE/2.0f);
	sf::Vector2f B = center + sf::Vector2f( VIEW_SIZE/2.0f, -VIEW_SIZE/2.0f);
	sf::Vector2f C = center + sf::Vector2f( VIEW_SIZE/2.0f,  VIEW_SIZE/2.0f);
	sf::Vector2f D = center + sf::Vector2f(-VIEW_SIZE/2.0f,  VIEW_SIZE/2.0f);

	sf::Vector2f sA = A - view.getCenter();
	sf::Vector2f sB = B - view.getCenter();
	sf::Vector2f sC = C - view.getCenter();
	sf::Vector2f sD = D - view.getCenter();

	gScreenSize = window.getSize();

	float viewScale = 600.0f / gScreenSize.x;

	sf::Vector2f nA = sf::Vector2f((sA.x / view.getSize().x + 0.5f)*gScreenSize.x, (sA.y / view.getSize().y + 0.5f)*gScreenSize.y);
	sf::Vector2f nB = sf::Vector2f((sB.x / view.getSize().x + 0.5f)*gScreenSize.x, (sB.y / view.getSize().y + 0.5f)*gScreenSize.y);
	sf::Vector2f nC = sf::Vector2f((sC.x / view.getSize().x + 0.5f)*gScreenSize.x, (sC.y / view.getSize().y + 0.5f)*gScreenSize.y);
	sf::Vector2f nD = sf::Vector2f((sD.x / view.getSize().x + 0.5f)*gScreenSize.x, (sD.y / view.getSize().y + 0.5f)*gScreenSize.y);

	window.draw(gLevelBackground);

	DrawArea(AT_NORMAL, window, view, sf::FloatRect(0.0f, 0.0f, nA.x, nA.y));
	DrawArea(AT_NORMAL, window, view, sf::FloatRect(nB.x, 0.0f, gScreenSize.x-nB.x, nB.y));
	DrawArea(AT_NORMAL, window, view, sf::FloatRect(nC.x, nC.y, gScreenSize.x-nC.x, gScreenSize.y-nC.y));
	DrawArea(AT_NORMAL, window, view, sf::FloatRect(0.0f, nD.y, nD.x, gScreenSize.y-nD.y));

	DrawArea(AT_MALE, window, view, sf::FloatRect(nA.x, 0, nB.x-nA.x, nA.y));
	DrawArea(AT_MALE, window, view, sf::FloatRect(nA.x, nD.y, nC.x-nD.x, gScreenSize.y-nC.y));

	DrawArea(AT_FEMALE, window, view, sf::FloatRect(0, nA.y, nA.x, nD.y-nA.y));
	DrawArea(AT_FEMALE, window, view, sf::FloatRect(nB.x, nB.y, gScreenSize.x-nB.x, nC.y-nB.y));

	DrawArea(AT_BOTH, window, view, sf::FloatRect(nA.x, nA.y, nC.x-nA.x, nC.y-nA.y));

	// reset viewport
	view.setViewport(sf::FloatRect(0, 0, 1, 1));
	window.setView(view);

	gFemale.Draw(window);
	gMale.Draw(window);

	/*sf::CircleShape cs(4.0f);
	cs.setOrigin(4.0f, 4.0f);
	cs.setFillColor(sf::Color(128, 128, 128));

	cs.setPosition(A);
	window.draw(cs);
	cs.setPosition(B);
	window.draw(cs);
	cs.setPosition(C);
	window.draw(cs);
	cs.setPosition(D);
	window.draw(cs);
	*/
	if (activeDialogue.IsActive())
		activeDialogue.Draw(window);

	gInventory.Draw(window);
}

void NormalizeLookAt(sf::Vector2f& lookAt, sf::View& view)
{
	if (lookAt.x - view.getSize().x * 0.5f  < 0.f)
		lookAt.x = view.getSize().x * 0.5f;
	else if (lookAt.x + view.getSize().x * 0.5f > gLevelBackground.getLocalBounds().width)
		lookAt.x = gLevelBackground.getLocalBounds().width - view.getSize().x * 0.5f;
	if (lookAt.y - view.getSize().y * 0.5f <  0.f)
		lookAt.y = view.getSize().y * 0.5f;
	else if (lookAt.y + view.getSize().y * 0.5f > gLevelBackground.getLocalBounds().height)
		lookAt.y = gLevelBackground.getLocalBounds().height - view.getSize().y * 0.5f;
}

void PlayLevel(sf::RenderWindow& window, float viewHeight)
{
	if(window.isOpen() == false)
		return;

	gInventory.items.clear();

	sf::Clock fpsTimer;
	int frames = 0;

	sf::Clock frameClock;
	float accumulator = 0.0f;

	float blackColor = 1.0f;
	const float blackColorTime = 0.4f;

	currLookAt = (gMale.pos+gFemale.pos) * 0.5f;
	sf::Vector2u screenSize = window.getSize();
	if(screenSize.x == 0) screenSize.x = 0;
	gView.setSize(sf::Vector2f(viewHeight *  screenSize.x / screenSize.y, viewHeight));
	gView.setCenter(currLookAt);
	NormalizeLookAt(currLookAt, gView);

	gCurrentHiddenObject = 0;

	// FADE IN
	while(window.isOpen())
	{
		sf::Event event;

		while(window.pollEvent(event))
		{
			if(event.type == sf::Event::Closed)
				window.close();
			else if ( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape )
			{
				window.close();
			}   
		}

		accumulator += frameClock.getElapsedTime().asSeconds();
		frameClock.restart();

		if(accumulator > 6.0f / 60.0f) accumulator = 6.0f / 60.0f;

		while(accumulator >= 1.0f / 60.0f)
		{
			accumulator -= 1.0f / 60.0f;
			blackColor -= 1.0f/60.0f/blackColorTime;
		}

		if(blackColor <= 0) break;

		window.clear(sf::Color(128, 64, 0));
		DrawLevel(window, frames, gView, fpsTimer, viewHeight);
		sf::RectangleShape rs(sf::Vector2f(10000, 10000));
		rs.setOrigin(5000, 5000);
		rs.setFillColor(sf::Color(0, 0, 0, blackColor*255));
		window.draw(rs);
		window.display();
	}

	// GAMEPLAY
	bool gameDone=false;
	while(window.isOpen() && !gameDone && (gCurrentHiddenObject < hiddenObjCount || activeDialogue.IsActive()))
	{
		sf::Event event;

		while(window.pollEvent(event))
		{
			if(event.type == sf::Event::Closed)
				window.close();
			else if ( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape )
			{
				window.close();
			} else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Q)
				gameDone = true;
		}

		accumulator += frameClock.getElapsedTime().asSeconds();
		frameClock.restart();

		if(accumulator > 6.0f / 60.0f) accumulator = 6.0f / 60.0f;

		while(accumulator >= 1.0f / 60.0f)
		{
			accumulator -= 1.0f / 60.0f;

			if (activeDialogue.IsActive())
				activeDialogue.Step();
			else
			{
				// update there...
				gFemale.Step();
				gMale.Step();
			}

			for (int i =0; i < gGameObjects.size(); ++i)
				gGameObjects[i]->Step();

			gInventory.Step();

			sf::Vector2f destLookAt = (gMale.pos+gFemale.pos) * 0.5f;
			NormalizeLookAt(destLookAt, gView);
			currLookAt = destLookAt*0.05f + currLookAt*0.95f;
		}

		window.clear(sf::Color(128, 64, 0));
		DrawLevel(window, frames, gView, fpsTimer, viewHeight);
		window.display();
	}

	if (gCurrentHiddenObject == hiddenObjCount)
		gWinSound.play();

	// FADE OUT
	blackColor = 0.0f;
	while(window.isOpen())
	{
		sf::Event event;

		while(window.pollEvent(event))
		{
			if(event.type == sf::Event::Closed)
				window.close();
			else if ( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape )
			{
				window.close();
			}   
		}

		accumulator += frameClock.getElapsedTime().asSeconds();
		frameClock.restart();

		if(accumulator > 6.0f / 60.0f) accumulator = 6.0f / 60.0f;

		while(accumulator >= 1.0f / 60.0f)
		{
			accumulator -= 1.0f / 60.0f;
			blackColor += 1.0f/60.0f/blackColorTime;
		}

		if(blackColor >= 1.0f) break;

		window.clear(sf::Color(128, 64, 0));
		DrawLevel(window, frames, gView, fpsTimer, viewHeight);
		sf::RectangleShape rs(sf::Vector2f(10000, 10000));
		rs.setOrigin(5000, 5000);
		rs.setFillColor(sf::Color(0, 0, 0, blackColor*255));
		window.draw(rs);
		window.display();
	}
}